// ==UserScript== // @name 页面解题不可用,新增出题助记 咽沙学习小助手测试版V0.93 // @namespace http://tampermonkey.net/ // @version 0.93 // @description 页面答题功能不可用,新增出题助记功能 // @author YeansyAwa // @match *://*/* // @grant GM_addStyle // @grant GM_xmlhttpRequest // ==/UserScript== (function() { 'use strict'; const API_SECRET_KEY = "sk-zkix22izlS26fVKhfAtHnRa2A8rT9xZyQqAu6Sf8NfiXPPtdYEYN"; const BASE_URL = "https://model-bridge.okeeper.com/v1/"; // 添加 CSS 样式 - 确保样式定义正确 GM_addStyle(` /* 确保所有相关元素都有合适的样式 */ #button-container { width: 250px; height: 60px; border-radius: 15px; font-size: 18px; position: fixed; right: 20px; bottom: 180px; z-index: 10000; cursor: pointer; font-family: "STKaiti", "华文楷体", "Kaiti", serif; overflow: visible; color: black; background: linear-gradient(135deg, #ffecb3, #ffdead); transition: all 0.3s ease-in-out; } .option-button { width: 250px; height: 60px; border-radius: 15px; border: none; background-color: #fff9db; cursor: pointer; font-family: "STKaiti", "华文楷体", "Kaiti", serif; display: none; text-align: left; position: absolute; left: 0; top: -60px; opacity: 0; transition: all 0.3s ease-in-out; } #chat-window, #auto-answer-chat-window, #quiz-memory-chat-window { width: 300px; height: 400px; background-color: #e6e6fa; border: 1px solid #ccc; position: fixed; bottom: 60px; right: 20px; z-index: 9999; box-shadow: 0 0 10px rgba(0,0,0,0.2); padding: 10px; border-radius: 5px; overflow: hidden; display: none; } #chat-content, #auto-answer-chat-content, #quiz-memory-chat-content { height: calc(100% - 120px); overflow-y: auto; } #input-container { position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: center; background-color: #fff; border-top: 1px solid #ccc; } #chat-input { width: calc(100% - 70px); height: 30px; margin: 5px; box-sizing: border-box; } #send-button { width: 50px; height: 30px; margin: 5px; box-sizing: border-box; } .copy-button { width: 100%; height: 30px; margin: 5px 0; box-sizing: border-box; background-color: #f0f0f0; border: 1px solid #ccc; cursor: pointer; text-align: center; line-height: 30px; } @keyframes gradientBG { 0% { background-color: #ffecb3; } 50% { background-color: #fffdd0; } 100% { background-color: #ffdead; } } button#show-hide-chat-button { animation: gradientBG 5s infinite; } `); function createButtonContainer() { const buttonContainer = document.createElement('div'); buttonContainer.id = 'button-container'; return buttonContainer; } function createParentButton(buttonContainer) { const parentButton = document.createElement('button'); parentButton.textContent = '咽沙学习小助手测试版 V0.93'; parentButton.style.width = '100%'; parentButton.style.height = '100%'; parentButton.style.border = 'none'; parentButton.style.backgroundColor = 'transparent'; parentButton.style.cursor = 'pointer'; parentButton.style.fontFamily = '"STKaiti", "华文楷体", "Kaiti", serif'; parentButton.style.fontSize = '18px'; buttonContainer.appendChild(parentButton); return parentButton; } function createOptionButtons(buttonContainer) { for (let i = 0; i < 5; i++) { const optionButton = document.createElement('button'); optionButton.className = 'option-button'; if (i === 4) { // 对话GPT按钮 optionButton.textContent = '-对话GPT 【本按钮可切换窗口显示、隐藏】'; optionButton.onclick = () => toggleChatWindowVisibility('chat-window'); } else if (i === 1) { // 获取页面自动解答按钮 optionButton.textContent = '-获取页面自动解答'; optionButton.onclick = () => { toggleChatWindowVisibility('auto-answer-chat-window'); generateAutoAnswer(); }; } else if (i === 2) { // 出题助记按钮 optionButton.textContent = '-出题助记【共18题】'; optionButton.onclick = () => toggleChatWindowVisibility('quiz-memory-chat-window'); } else { optionButton.onclick = () => parentButton.click(); // 收起子容器 } buttonContainer.appendChild(optionButton); } } function toggleChatWindowVisibility(chatWindowId) { const chatWindow = document.getElementById(chatWindowId); chatWindow.style.display = chatWindow.style.display === 'none' ? 'block' : 'none'; } function getPageText() { let allText = ''; const texts = []; const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false); while (walker.nextNode()) { const node = walker.currentNode; if (node.parentElement.tagName !== 'SCRIPT' && node.parentElement.tagName !== 'STYLE') { texts.push(node.nodeValue.trim()); } } return texts.filter(text => text).join('\n'); } async function sendMessageToAI(message, isQuizMemory = false) { try { const response = await fetch(`${BASE_URL}chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${API_SECRET_KEY}` }, body: JSON.stringify({ model: "gpt-3.5-turbo", messages: [ {"role": "system", "content": "您是一位乐于助人的助手。"}, {"role": "user", "content": message}, ...(isQuizMemory ? [{"role": "assistant", "content": "请根据以上信息生成18道选择题,帮助我更好地记住这些知识点。"}] : []) ] }) }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); if (!data.choices || !data.choices.length) throw new Error('来自AI服务的回答无效。'); return data; } catch (error) { console.error("获取AI回答时出错:", error); throw error; } } function createChatWindow(isAutoAnswer, isQuizMemory) { const chatWindowId = isQuizMemory ? 'quiz-memory-chat-window' : (isAutoAnswer ? 'auto-answer-chat-window' : 'chat-window'); const chatWindow = document.createElement('div'); chatWindow.id = chatWindowId; const chatContentId = `${chatWindowId}-content`; const chatContent = document.createElement('div'); chatContent.id = chatContentId; chatContent.className = 'chat-content'; chatWindow.appendChild(chatContent); if (isQuizMemory) { // 出题助记专属逻辑 const inputContainer = document.createElement('div'); inputContainer.id = 'input-container'; const userInput = document.createElement('input'); userInput.type = 'text'; userInput.placeholder = '在此输入你想记忆的知识...'; inputContainer.appendChild(userInput); const sendButton = document.createElement('button'); sendButton.textContent = '发送'; sendButton.onclick = async function() { const userMessage = userInput.value.trim(); if (userMessage) { userInput.value = ''; const loadingMessage = document.createElement('div'); loadingMessage.textContent = '正在加载中…请耐心等待'; chatContent.appendChild(loadingMessage); chatContent.scrollTop = chatContent.scrollHeight; try { const apiResponse = await sendMessageToAI(userMessage, true); // 在这里指定这是出题助记请求 appendChatMessage(chatContent, apiResponse.choices[0].message.content); addCopyButton(chatContent, apiResponse.choices[0].message.content); setTimeout(() => chatContent.removeChild(loadingMessage), 0); } catch (error) { const errorMessage = document.createElement('div'); errorMessage.textContent = '获取解答时出错,请稍后再试。'; chatContent.appendChild(errorMessage); chatContent.scrollTop = chatContent.scrollHeight; setTimeout(() => chatContent.removeChild(loadingMessage), 0); } } }; inputContainer.appendChild(sendButton); chatWindow.appendChild(inputContainer); } else { // 对话GPT窗口逻辑保持不变... const inputContainer = document.createElement('div'); inputContainer.id = 'input-container'; const userInput = document.createElement('input'); userInput.type = 'text'; userInput.placeholder = '在这里输入你的问题...'; inputContainer.appendChild(userInput); const sendButton = document.createElement('button'); sendButton.textContent = '发送'; sendButton.onclick = async function() { const userMessage = userInput.value.trim(); if (userMessage) { userInput.value = ''; const loadingMessage = document.createElement('div'); loadingMessage.textContent = '正在加载中…请耐心等待'; chatContent.appendChild(loadingMessage); chatContent.scrollTop = chatContent.scrollHeight; try { const apiResponse = await sendMessageToAI(userMessage); appendChatMessage(chatContent, apiResponse.choices[0].message.content); addCopyButton(chatContent, apiResponse.choices[0].message.content); setTimeout(() => chatContent.removeChild(loadingMessage), 0); } catch (error) { const errorMessage = document.createElement('div'); errorMessage.textContent = '获取解答时出错,请稍后再试。'; chatContent.appendChild(errorMessage); chatContent.scrollTop = chatContent.scrollHeight; setTimeout(() => chatContent.removeChild(loadingMessage), 0); } } }; inputContainer.appendChild(sendButton); chatWindow.appendChild(inputContainer); } document.body.appendChild(chatWindow); } function appendChatMessage(container, message) { const messageDiv = document.createElement('div'); messageDiv.innerHTML = message.replace(/\n/g, '
'); container.appendChild(messageDiv); container.scrollTop = container.scrollHeight; // 自动滚动到最底部 } function addCopyButton(container, content) { // 移除旧的复制按钮(如果有) const oldCopyButton = container.querySelector('.copy-button'); if (oldCopyButton) { container.removeChild(oldCopyButton); } // 创建新的复制按钮 const copyButton = document.createElement('div'); copyButton.className = 'copy-button'; copyButton.textContent = '点击复制此次回答'; copyButton.onclick = () => navigator.clipboard.writeText(content) .then(() => console.log('回答已复制到剪贴板')) .catch(err => console.error('无法复制回答:', err)); container.insertBefore(copyButton, container.lastElementChild); // 插入到输入框的上方 container.scrollTop = container.scrollHeight; // 再次确保滚动到最底部 } function generateAutoAnswer() { const pageText = getPageText(); const loadingMessage = document.createElement('div'); loadingMessage.textContent = '正在生成页面解答...'; const chatContent = document.getElementById('auto-answer-chat-content'); chatContent.appendChild(loadingMessage); chatContent.scrollTop = chatContent.scrollHeight; sendMessageToAI(pageText) .then(response => { appendChatMessage(chatContent, response.choices[0].message.content); addCopyButton(chatContent, response.choices[0].message.content); }) .catch(error => { const errorMessage = document.createElement('div'); errorMessage.textContent = '生成页面解答时出错,请稍后再试。'; chatContent.appendChild(errorMessage); }) .finally(() => { setTimeout(() => chatContent.removeChild(loadingMessage), 0); }); } const buttonContainer = createButtonContainer(); document.body.insertBefore(buttonContainer, document.body.firstChild); const parentButton = createParentButton(buttonContainer); let isExpanded = false; parentButton.onclick = function(event) { if (isExpanded) { hideButtons(); } else { showButtons(); } isExpanded = !isExpanded; }; function forceRedraw(element) { element.style.zIndex = 1; void element.offsetWidth; element.style.zIndex = ''; } function showButtons() { const buttons = Array.from(buttonContainer.querySelectorAll('.option-button')); const initialTopOffset = -60; buttons.forEach((button, index) => { setTimeout(() => { button.style.display = 'block'; button.style.top = `${initialTopOffset - index * 60}px`; button.style.opacity = '1'; forceRedraw(button); }, index * 200); }); } function hideButtons() { const buttons = Array.from(buttonContainer.querySelectorAll('.option-button')).reverse(); buttons.forEach((button, index) => { setTimeout(() => { button.style.opacity = '0'; setTimeout(() => { button.style.display = 'none'; button.style.top = ''; forceRedraw(button); }, 200); }, index * 200); }); } createOptionButtons(buttonContainer); createChatWindow(false); // 对话GPT窗口 createChatWindow(true); // 获取页面自动解答窗口 createChatWindow(false, true); // 出题助记专属聊天窗口 })();